package cn.desk.commons.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import cn.desk.commons.entity.BaseEntity;
import cn.desk.commons.entity.MessageInfo;
import cn.desk.commons.entity.PageMode;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.interceptor.PreResultListener;

public abstract class BaseAction<T> extends ActionSupport implements Preparable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	protected PageMode<T> pageMode;

	protected T t;

	private Class<T> entityClass;

	private List<MessageInfo> actionErrorList;

	private List<MessageInfo> actionMessageList;

	private Map<String, List<MessageInfo>> fieldErrorMap;

	private PreResultListener preResultListener;

	public HttpServletResponse getResponse() {
		return ServletActionContext.getResponse();
	}

	public HttpServletRequest getRequest() {
		return ServletActionContext.getRequest();
	}

	public HttpSession getSession() {
		return getRequest().getSession();
	}

	public ServletContext getServletContext() {
		return ServletActionContext.getServletContext();
	}

	public Object getSessionValue(String key) {
		return getSession().getAttribute(key);
	}

	public void setSession(String key, Object value) {
		getSession().setAttribute(key, value);
	}

	public void removeSession(String key) {
		getSession().removeAttribute(key);
	}

	public PageMode<T> getPageMode() {
		if (pageMode != null) {
			if (pageMode.getPageSize() == null) {
				Object page = getSessionValue("PAGESIZE");
				if (page == null) {
					pageMode.setPageSize(10);
				} else {
					pageMode.setPageSize((Integer) page);
				}
			}
			if (pageMode.getCurrentPage() == null) {
				pageMode.setCurrentPage(0);
			}
		}
		return pageMode;
	}

	public void setPageMode(PageMode<T> pageMode) {
		this.pageMode = pageMode;
	}

	public abstract String getModeName();

	public List<MessageInfo> getActionErrorList() {
		return actionErrorList;
	}

	public void setActionErrorList(List<MessageInfo> actionErrorList) {
		this.actionErrorList = actionErrorList;
	}

	public void addActionError(String message, BaseEntity entity,
			Object... values) {
		addActionError(new MessageInfo(message, entity, values));
	}

	public void addActionError(String message) {
		addActionError(new MessageInfo(message));
	}

	public void addActionMessage(String message, BaseEntity entity,
			Object... values) {
		if (actionMessageList == null) {
			actionMessageList = new ArrayList<MessageInfo>();
		}
		actionMessageList.add(new MessageInfo(message, entity, values));
	}

	public void addActionMessage(String message) {
		addActionMessage(message, null);
	}

	public List<MessageInfo> getActionMessage() {
		return actionMessageList;
	}

	public void addActionMessage(List<MessageInfo> actionMessageList) {
		this.actionMessageList = actionMessageList;
	}

	public void setFieldErrorMap(Map<String, List<MessageInfo>> fieldErrorMap) {
		this.fieldErrorMap = fieldErrorMap;
	}

	public void addFieldError(String fieldId, String message,
			BaseEntity entity, Object... values) {
		if (fieldErrorMap == null) {
			fieldErrorMap = new HashMap<String, List<MessageInfo>>();
		}
		List<MessageInfo> messages = fieldErrorMap.get(fieldId);
		if (messages == null) {
			messages = new ArrayList<MessageInfo>();
		}
		messages.add(new MessageInfo(message, entity, values));
		fieldErrorMap.put(fieldId, messages);
	}

	public void addFieldError(String fieldId, String message) {
		addFieldError(fieldId, message, null);
	}

	public Map<String, List<MessageInfo>> getFieldErrorMap() {
		return fieldErrorMap;
	}

	public void addActionError(MessageInfo messageInfo) {
		if (actionErrorList == null) {
			actionErrorList = new ArrayList<MessageInfo>();
		}
		actionErrorList.add(messageInfo);

	}

	public boolean hasActionErrors() {
		if (actionErrorList == null) {
			return super.hasActionErrors();
		}
		return super.hasActionErrors() || !actionErrorList.isEmpty();
	}

	public T getT() {
		return t;
	}

	public void setT(T t) {
		this.t = t;
	}

	public boolean hasActionMessages() {
		if (actionMessageList == null) {
			return super.hasActionMessages();
		}
		return super.hasActionMessages() || !actionMessageList.isEmpty();
	}

	public boolean hasErrors() {
		return hasActionErrors() || hasFieldErrors();
	}

	public boolean hasFieldErrors() {
		if (fieldErrorMap == null) {
			return super.hasFieldErrors();
		}
		return super.hasFieldErrors() || !fieldErrorMap.isEmpty();
	}

	public Class<T> getEntityClass() {
		return entityClass;
	}

	public void setEntityClass(Class<T> entityClass) {
		this.entityClass = entityClass;
	}

	@Override
	public void prepare() throws Exception {
		if (entityClass != null) {
			t = entityClass.newInstance();
		}
	}

	public PreResultListener getPreResultListener() {
		return preResultListener;
	}

	public void setPreResultListener(PreResultListener preResultListener) {
		this.preResultListener = preResultListener;
		ActionInvocation invocation = ActionContext.getContext()
				.getActionInvocation();
		invocation.addPreResultListener(preResultListener);
	}

	@Override
	public void clearErrors() {
		if (actionErrorList != null) {
			actionErrorList.clear();
		}
		if (fieldErrorMap != null) {
			fieldErrorMap.clear();
		}
		super.clearErrors();
	}
}
